/*     */ package com.zimbra.cs.rmgmt;
/*     */ 
/*     */ import com.zimbra.common.account.Key.ServerBy;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.CliUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.Server;
/*     */ import com.zimbra.cs.index.LuceneDirectory;
/*     */ import com.zimbra.cs.index.LuceneIndex;
/*     */ import com.zimbra.cs.service.admin.GetMailQueue;
/*     */ import java.io.File;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.PrintStream;
/*     */ import java.util.Arrays;
/*     */ import java.util.Collections;
/*     */ import java.util.HashMap;
/*     */ import java.util.Iterator;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.concurrent.atomic.AtomicInteger;
/*     */ import org.apache.lucene.analysis.standard.StandardAnalyzer;
/*     */ import org.apache.lucene.document.Document;
/*     */ import org.apache.lucene.document.Field;
/*     */ import org.apache.lucene.document.Field.Index;
/*     */ import org.apache.lucene.document.Field.Store;
/*     */ import org.apache.lucene.document.Field.TermVector;
/*     */ import org.apache.lucene.index.IndexReader;
/*     */ import org.apache.lucene.index.IndexWriter;
/*     */ import org.apache.lucene.index.IndexWriter.MaxFieldLength;
/*     */ import org.apache.lucene.index.Term;
/*     */ import org.apache.lucene.index.TermDocs;
/*     */ import org.apache.lucene.index.TermEnum;
/*     */ import org.apache.lucene.search.Filter;
/*     */ import org.apache.lucene.search.IndexSearcher;
/*     */ import org.apache.lucene.search.Query;
/*     */ import org.apache.lucene.search.ScoreDoc;
/*     */ import org.apache.lucene.search.Searcher;
/*     */ import org.apache.lucene.search.TopDocs;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class RemoteMailQueue
/*     */ {
/*  60 */   private static Map<String, RemoteMailQueue> mMailQueueCache = new HashMap();
/*     */   public static final int MAIL_QUEUE_INDEX_FLUSH_THRESHOLD = 1000;
/*     */   
/*  63 */   public static RemoteMailQueue getRemoteMailQueue(Server server, String queueName, boolean forceScan) throws ServiceException { synchronized (mMailQueueCache) {
/*  64 */       String cacheKey = server.getId() + "-" + queueName;
/*     */       
/*     */ 
/*  67 */       RemoteMailQueue queue = (RemoteMailQueue)mMailQueueCache.get(cacheKey);
/*  68 */       if (queue != null) {
/*  69 */         if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("queue cache: exists " + queue);
/*  70 */         if (forceScan) {
/*  71 */           if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("queue cache: forcing scan " + queue);
/*  72 */           queue.startScan(server, queueName);
/*     */         }
/*     */       } else {
/*  75 */         queue = new RemoteMailQueue(server, queueName, true);
/*  76 */         if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("queue cache: new object " + queue);
/*  77 */         mMailQueueCache.put(cacheKey, queue);
/*     */       }
/*  79 */       return queue;
/*     */     }
/*     */   }
/*     */   
/*     */   public static enum QueueAttr {
/*  84 */     id,  time,  size,  from,  to,  host,  addr,  reason,  filter,  todomain,  fromdomain,  received;
/*     */     
/*     */     private QueueAttr() {} }
/*     */   
/*  88 */   public static enum QueueAction { hold,  release,  delete,  requeue;
/*     */     
/*     */     private QueueAction() {}
/*     */   }
/*     */   
/*  93 */   static AtomicInteger mVisitorIdCounter = new AtomicInteger(0);
/*     */   
/*  95 */   AtomicInteger mNumMessages = new AtomicInteger(0);
/*     */   
/*     */   public int getNumMessages() {
/*  98 */     return this.mNumMessages.get();
/*     */   }
/*     */   
/*     */   private class QueueItemVisitor implements RemoteResultParser.Visitor
/*     */   {
/*     */     final int mId;
/*     */     
/*     */     QueueItemVisitor() {
/* 106 */       this.mId = RemoteMailQueue.mVisitorIdCounter.incrementAndGet();
/*     */     }
/*     */     
/*     */     public void handle(int lineNo, Map<String, String> map) throws IOException
/*     */     {
/* 111 */       if (map == null) {
/* 112 */         return;
/*     */       }
/*     */       
/* 115 */       if ((RemoteMailQueue.this.mNumMessages.get() > 0) && (RemoteMailQueue.this.mNumMessages.get() % 1000 == 0))
/*     */       {
/* 117 */         RemoteMailQueue.this.reopenIndexWriter();
/*     */       }
/* 119 */       RemoteMailQueue.this.mNumMessages.incrementAndGet();
/*     */       
/* 121 */       Document doc = new Document();
/*     */       
/* 123 */       String id = (String)map.get(RemoteMailQueue.QueueAttr.id.toString());
/* 124 */       if (id == null) {
/* 125 */         throw new IOException("no ID defined near line=" + lineNo);
/*     */       }
/* 127 */       doc.add(new Field(RemoteMailQueue.QueueAttr.id.toString(), id.toLowerCase(), Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
/*     */       
/*     */ 
/* 130 */       String time = (String)map.get(RemoteMailQueue.QueueAttr.time.toString());
/* 131 */       if ((time != null) && (time.length() > 0)) {
/* 132 */         long timeMillis = Long.parseLong(time) * 1000L;
/* 133 */         doc.add(new Field(RemoteMailQueue.QueueAttr.time.toString(), Long.toString(timeMillis), Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
/*     */       }
/*     */       
/*     */ 
/* 137 */       RemoteMailQueue.this.addSimpleField(doc, map, RemoteMailQueue.QueueAttr.size);
/* 138 */       RemoteMailQueue.this.addSimpleField(doc, map, RemoteMailQueue.QueueAttr.addr);
/* 139 */       RemoteMailQueue.this.addSimpleField(doc, map, RemoteMailQueue.QueueAttr.host);
/* 140 */       RemoteMailQueue.this.addSimpleField(doc, map, RemoteMailQueue.QueueAttr.filter);
/* 141 */       RemoteMailQueue.this.addSimpleField(doc, map, RemoteMailQueue.QueueAttr.reason);
/* 142 */       RemoteMailQueue.this.addSimpleField(doc, map, RemoteMailQueue.QueueAttr.received);
/*     */       
/* 144 */       String from = (String)map.get(RemoteMailQueue.QueueAttr.from.toString());
/* 145 */       if ((from != null) && (from.length() > 0)) {
/* 146 */         RemoteMailQueue.this.addEmailAddress(doc, from, RemoteMailQueue.QueueAttr.from, RemoteMailQueue.QueueAttr.fromdomain);
/*     */       }
/*     */       
/* 149 */       String toWithCommas = (String)map.get(RemoteMailQueue.QueueAttr.to.toString());
/* 150 */       if ((toWithCommas != null) && (toWithCommas.length() > 0)) {
/* 151 */         String[] toArray = toWithCommas.split(",");
/* 152 */         for (String to : toArray) {
/* 153 */           RemoteMailQueue.this.addEmailAddress(doc, to, RemoteMailQueue.QueueAttr.to, RemoteMailQueue.QueueAttr.todomain);
/*     */         }
/*     */       }
/*     */       
/* 157 */       if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("[scan id=" + this.mId + "] " + doc);
/* 158 */       RemoteMailQueue.this.mIndexWriter.addDocument(doc);
/*     */     }
/*     */   }
/*     */   
/*     */   void addSimpleField(Document doc, Map<String, String> map, QueueAttr attr) {
/* 163 */     String value = (String)map.get(attr.toString());
/* 164 */     if ((value != null) && (value.length() > 0)) {
/* 165 */       doc.add(new Field(attr.toString(), value.toLowerCase(), Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
/*     */     }
/*     */   }
/*     */   
/*     */   void addEmailAddress(Document doc, String address, QueueAttr addressAttr, QueueAttr domainAttr)
/*     */   {
/* 171 */     address = address.toLowerCase();
/* 172 */     doc.add(new Field(addressAttr.toString(), address, Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
/*     */     
/* 174 */     String[] parts = address.split("@");
/* 175 */     if ((parts != null) && (parts.length > 1)) {
/* 176 */       doc.add(new Field(domainAttr.toString(), parts[1], Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
/*     */     }
/*     */   }
/*     */   
/*     */   private class QueueHandler implements RemoteBackgroundHandler {
/*     */     private QueueHandler() {}
/*     */     
/*     */     public void read(InputStream stdout, InputStream stderr) {
/*     */       try {
/* 185 */         RemoteMailQueue.this.mScanStartTime = System.currentTimeMillis();
/* 186 */         RemoteMailQueue.QueueItemVisitor v = new RemoteMailQueue.QueueItemVisitor(RemoteMailQueue.this);
/* 187 */         if (ZimbraLog.rmgmt.isDebugEnabled()) { ZimbraLog.rmgmt.debug("starting scan with visitor id=" + v.mId + " " + RemoteMailQueue.this.mDescription);
/*     */         }
/* 189 */         RemoteMailQueue.this.clearIndexInternal();
/* 190 */         RemoteMailQueue.this.openIndexWriter();
/* 191 */         RemoteMailQueue.this.mNumMessages.set(0);
/* 192 */         RemoteResultParser.parse(stdout, v);
/* 193 */         RemoteMailQueue.this.closeIndexWriter();
/* 194 */         RemoteMailQueue.this.mScanEndTime = System.currentTimeMillis();
/* 195 */         if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("finished scan with visitor id=" + v.mId + " total=" + RemoteMailQueue.this.mNumMessages + " " + RemoteMailQueue.this.mDescription);
/* 196 */         byte[] err = ByteUtil.getContent(stderr, 0);
/* 197 */         if ((err != null) && (err.length > 0)) {
/* 198 */           ZimbraLog.rmgmt.error("error scanning " + this + ": " + new String(err));
/*     */         }
/*     */       } catch (IOException ioe) {
/* 201 */         error(ioe);
/*     */       } finally {
/* 203 */         synchronized (RemoteMailQueue.this.mScanLock) {
/* 204 */           RemoteMailQueue.this.mScanInProgress = false;
/* 205 */           RemoteMailQueue.this.mScanLock.notifyAll();
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */     public void error(Throwable t)
/*     */     {
/* 212 */       ZimbraLog.rmgmt.error("error when scanning mail queue " + RemoteMailQueue.this.mQueueName + " on host " + RemoteMailQueue.this.mServerName, t);
/*     */     }
/*     */   }
/*     */   
/* 216 */   Object mScanLock = new Object();
/*     */   boolean mScanInProgress;
/*     */   long mScanStartTime;
/*     */   
/*     */   public long getScanTime()
/*     */   {
/* 222 */     synchronized (this.mScanLock) {
/* 223 */       if (this.mScanInProgress) {
/* 224 */         return System.currentTimeMillis();
/*     */       }
/* 226 */       return this.mScanEndTime;
/*     */     } }
/*     */   
/*     */   long mScanEndTime;
/*     */   final String mQueueName;
/*     */   final String mServerName;
/* 232 */   void clearIndexInternal() throws IOException { IndexWriter writer = null;
/*     */     try {
/* 234 */       if (ZimbraLog.rmgmt.isDebugEnabled()) {
/* 235 */         ZimbraLog.rmgmt.debug("clearing index (" + this.mIndexPath + ") for " + this);
/*     */       }
/* 237 */       writer = new IndexWriter(LuceneDirectory.open(this.mIndexPath), new StandardAnalyzer(LuceneIndex.VERSION), true, IndexWriter.MaxFieldLength.LIMITED);
/*     */       
/*     */ 
/* 240 */       this.mNumMessages.set(0);
/*     */     } finally {
/* 242 */       if (writer != null) {
/* 243 */         writer.close();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public void clearIndex() throws ServiceException {
/* 249 */     synchronized (this.mScanLock) {
/*     */       try {
/* 251 */         if (this.mScanInProgress) {
/* 252 */           throw ServiceException.TEMPORARILY_UNAVAILABLE();
/*     */         }
/* 254 */         clearIndexInternal();
/*     */       } catch (IOException ioe) {
/* 256 */         throw ServiceException.FAILURE("could not clear queue cache", ioe);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public void startScan(Server server, String queueName) throws ServiceException {
/* 262 */     synchronized (this.mScanLock) {
/* 263 */       if (this.mScanInProgress)
/*     */       {
/* 265 */         throw ServiceException.ALREADY_IN_PROGRESS("scan server=" + this.mServerName + " queue=" + this.mQueueName);
/*     */       }
/* 267 */       this.mScanInProgress = true;
/* 268 */       RemoteManager rm = RemoteManager.getRemoteManager(server);
/* 269 */       if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("initiating scan in background " + this);
/* 270 */       rm.executeBackground("zmqstat " + queueName, new QueueHandler(null));
/*     */     }
/*     */   }
/*     */   
/*     */   public boolean waitForScan(long timeout) {
/* 275 */     synchronized (this.mScanLock) {
/* 276 */       if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("scan wait " + this);
/* 277 */       long waitTime = timeout;
/* 278 */       long startTime = System.currentTimeMillis();
/* 279 */       while (this.mScanInProgress) {
/*     */         try {
/* 281 */           if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("scan wait time " + waitTime + "ms " + this);
/* 282 */           this.mScanLock.wait(waitTime);
/*     */           
/*     */ 
/* 285 */           if (!this.mScanInProgress) {
/* 286 */             if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("scan wait done " + this);
/* 287 */             break;
/*     */           }
/*     */           
/* 290 */           long now = System.currentTimeMillis();
/* 291 */           long timeSoFar = now - startTime;
/* 292 */           if (timeSoFar >= timeout) {
/* 293 */             if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("scan wait timed out " + this);
/* 294 */             break;
/*     */           }
/* 296 */           waitTime = timeout - timeSoFar;
/*     */         }
/*     */         catch (InterruptedException ie) {
/* 299 */           ZimbraLog.rmgmt.warn("interrupted while waiting for queue scan", ie);
/*     */         }
/*     */       }
/* 302 */       if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("scan wait returning progress=" + this.mScanInProgress + " " + this);
/* 303 */       return this.mScanInProgress;
/*     */     }
/*     */   }
/*     */   
/*     */   final String mDescription;
/*     */   IndexWriter mIndexWriter;
/*     */   private final File mIndexPath;
/*     */   private static final int MAX_REMOTE_EXECUTION_QUEUEIDS = 50;
/*     */   private static final int MAX_LENGTH_OF_QUEUEIDS = 12;
/*     */   public String toString() {
/* 313 */     return this.mDescription;
/*     */   }
/*     */   
/*     */   private RemoteMailQueue(Server server, String queueName, boolean scan) throws ServiceException {
/* 317 */     this.mServerName = server.getName();
/* 318 */     this.mQueueName = queueName;
/* 319 */     this.mDescription = ("[mail-queue: server=" + this.mServerName + " name=" + this.mQueueName + " hash=" + hashCode() + "]");
/* 320 */     this.mIndexPath = new File(LC.zimbra_tmp_directory.value() + File.separator + server.getId() + "-" + queueName);
/* 321 */     if (scan) {
/* 322 */       startScan(server, queueName);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   void openIndexWriter()
/*     */     throws IOException
/*     */   {
/* 331 */     if (ZimbraLog.rmgmt.isDebugEnabled()) {
/* 332 */       ZimbraLog.rmgmt.debug("opening indexwriter " + this);
/*     */     }
/* 334 */     this.mIndexWriter = new IndexWriter(LuceneDirectory.open(this.mIndexPath), new StandardAnalyzer(LuceneIndex.VERSION), true, IndexWriter.MaxFieldLength.LIMITED);
/*     */   }
/*     */   
/*     */   void closeIndexWriter()
/*     */     throws IOException
/*     */   {
/* 340 */     if (ZimbraLog.rmgmt.isDebugEnabled()) {
/* 341 */       ZimbraLog.rmgmt.debug("closing indexwriter " + this);
/*     */     }
/* 343 */     this.mIndexWriter.close();
/*     */   }
/*     */   
/*     */   void reopenIndexWriter() throws IOException {
/* 347 */     if (ZimbraLog.rmgmt.isDebugEnabled()) {
/* 348 */       ZimbraLog.rmgmt.debug("reopening indexwriter " + this);
/*     */     }
/* 350 */     this.mIndexWriter.close();
/* 351 */     this.mIndexWriter = new IndexWriter(LuceneDirectory.open(this.mIndexPath), new StandardAnalyzer(LuceneIndex.VERSION), false, IndexWriter.MaxFieldLength.LIMITED);
/*     */   }
/*     */   
/*     */   public static final class SummaryItem implements Comparable<SummaryItem>
/*     */   {
/*     */     private String mTerm;
/*     */     private int mCount;
/*     */     
/*     */     public SummaryItem(String term, int count)
/*     */     {
/* 361 */       this.mTerm = term;
/* 362 */       this.mCount = count;
/*     */     }
/*     */     
/*     */     public String term() {
/* 366 */       return this.mTerm;
/*     */     }
/*     */     
/*     */     public int count() {
/* 370 */       return this.mCount;
/*     */     }
/*     */     
/*     */     public int compareTo(SummaryItem other)
/*     */     {
/* 375 */       return other.mCount - this.mCount;
/*     */     }
/*     */   }
/*     */   
/*     */   public static class SearchResult
/*     */   {
/* 381 */     public Map<RemoteMailQueue.QueueAttr, List<RemoteMailQueue.SummaryItem>> sitems = new HashMap();
/*     */     public int hits;
/* 383 */     public List<Map<RemoteMailQueue.QueueAttr, String>> qitems = new LinkedList();
/*     */   }
/*     */   
/*     */   private void summarize(SearchResult result, IndexReader indexReader) throws IOException {
/* 387 */     TermEnum terms = indexReader.terms();
/* 388 */     boolean hasDeletions = indexReader.hasDeletions();
/*     */     do {
/* 390 */       Term term = terms.term();
/* 391 */       if (term != null) {
/* 392 */         String field = term.field();
/* 393 */         if ((field != null) && (field.length() > 0)) {
/* 394 */           QueueAttr attr = QueueAttr.valueOf(field);
/* 395 */           if ((attr == QueueAttr.addr) || (attr == QueueAttr.host) || (attr == QueueAttr.from) || (attr == QueueAttr.to) || (attr == QueueAttr.fromdomain) || (attr == QueueAttr.todomain) || (attr == QueueAttr.reason) || (attr == QueueAttr.received))
/*     */           {
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 404 */             List<SummaryItem> list = (List)result.sitems.get(attr);
/* 405 */             if (list == null) {
/* 406 */               list = new LinkedList();
/* 407 */               result.sitems.put(attr, list);
/*     */             }
/* 409 */             int count = 0;
/* 410 */             if (hasDeletions) {
/* 411 */               TermDocs termDocs = indexReader.termDocs(term);
/* 412 */               while (termDocs.next()) {
/* 413 */                 if (!indexReader.isDeleted(termDocs.doc())) {
/* 414 */                   count++;
/*     */                 }
/*     */               }
/*     */             } else {
/* 418 */               count = terms.docFreq();
/*     */             }
/* 420 */             if (count > 0) {
/* 421 */               list.add(new SummaryItem(term.text(), count));
/*     */             }
/*     */           }
/*     */         }
/*     */       }
/* 426 */     } while (terms.next());
/*     */   }
/*     */   
/*     */   private Map<QueueAttr, String> docToQueueItem(Document doc) {
/* 430 */     Map<QueueAttr, String> qitem = new HashMap();
/* 431 */     for (QueueAttr attr : QueueAttr.values()) {
/* 432 */       Field[] fields = doc.getFields(attr.toString());
/* 433 */       if (fields != null) {
/* 434 */         StringBuilder sb = new StringBuilder();
/* 435 */         boolean first = true;
/* 436 */         for (Field field : fields) {
/* 437 */           if (first) {
/* 438 */             first = false;
/*     */           } else {
/* 440 */             sb.append(",");
/*     */           }
/* 442 */           sb.append(field.stringValue());
/*     */         }
/* 444 */         if (attr == QueueAttr.id) {
/* 445 */           qitem.put(attr, sb.toString().toUpperCase());
/*     */         } else {
/* 447 */           qitem.put(attr, sb.toString());
/*     */         }
/*     */       }
/*     */     }
/* 451 */     return qitem;
/*     */   }
/*     */   
/*     */   private void list0(SearchResult result, IndexReader indexReader, int offset, int limit) throws IOException
/*     */   {
/* 456 */     if (ZimbraLog.rmgmt.isDebugEnabled()) {
/* 457 */       ZimbraLog.rmgmt.debug("listing offset=" + offset + " limit=" + limit + " " + this);
/*     */     }
/* 459 */     int max = indexReader.maxDoc();
/*     */     
/* 461 */     int skip = 0;
/* 462 */     int listed = 0;
/*     */     
/* 464 */     for (int i = 0; i < max; i++) {
/* 465 */       if (!indexReader.isDeleted(i))
/*     */       {
/*     */ 
/*     */ 
/* 469 */         if (skip < offset) {
/* 470 */           skip++;
/*     */         }
/*     */         else
/*     */         {
/* 474 */           Document doc = indexReader.document(i);
/* 475 */           Map<QueueAttr, String> qitem = docToQueueItem(doc);
/* 476 */           result.qitems.add(qitem);
/*     */           
/* 478 */           listed++;
/* 479 */           if (listed == limit)
/*     */             break;
/*     */         } }
/*     */     }
/* 483 */     result.hits = getNumMessages();
/*     */   }
/*     */   
/*     */   private void search0(SearchResult result, IndexReader indexReader, Query query, int offset, int limit) throws IOException
/*     */   {
/* 488 */     if (ZimbraLog.rmgmt.isDebugEnabled()) {
/* 489 */       ZimbraLog.rmgmt.debug("searching query=" + query + " offset=" + offset + " limit=" + limit + " " + this);
/*     */     }
/* 491 */     Searcher searcher = null;
/*     */     try {
/* 493 */       searcher = new IndexSearcher(indexReader);
/* 494 */       TopDocs topDocs = searcher.search(query, (Filter)null, limit);
/* 495 */       ScoreDoc[] hits = topDocs.scoreDocs;
/*     */       
/* 497 */       if (offset < hits.length) { int n;
/*     */         int n;
/* 499 */         if (limit <= 0) {
/* 500 */           n = hits.length;
/*     */         } else {
/* 502 */           n = Math.min(offset + limit, hits.length);
/*     */         }
/*     */         
/* 505 */         for (int i = offset; i < n; i++) {
/* 506 */           Document doc = searcher.doc(hits[i].doc);
/* 507 */           Map<QueueAttr, String> qitem = docToQueueItem(doc);
/* 508 */           result.qitems.add(qitem);
/*     */         }
/*     */       }
/* 511 */       result.hits = hits.length;
/*     */     } finally {
/* 513 */       if (searcher != null) {
/* 514 */         searcher.close();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public SearchResult search(Query query, int offset, int limit) throws ServiceException {
/* 520 */     result = new SearchResult();
/* 521 */     IndexReader indexReader = null;
/*     */     try {
/* 523 */       if (!this.mIndexPath.exists()) {
/* 524 */         return result;
/*     */       }
/* 526 */       indexReader = IndexReader.open(LuceneDirectory.open(this.mIndexPath));
/* 527 */       summarize(result, indexReader);
/* 528 */       if (query == null) {
/* 529 */         list0(result, indexReader, offset, limit);
/*     */       } else {
/* 531 */         search0(result, indexReader, query, offset, limit);
/*     */       }
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 544 */       return result;
/*     */     }
/*     */     catch (Exception e)
/*     */     {
/* 534 */       throw ServiceException.FAILURE("exception occurred searching mail queue", e);
/*     */     } finally {
/* 536 */       if (indexReader != null) {
/*     */         try {
/* 538 */           indexReader.close();
/*     */         } catch (IOException ioe) {
/* 540 */           ZimbraLog.rmgmt.warn("exception occured closing index reader from search", ioe);
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public void action(Server server, QueueAction action, String[] ids)
/*     */     throws ServiceException
/*     */   {
/* 551 */     if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("action=" + action + " ids=" + Arrays.deepToString(ids) + " " + this);
/* 552 */     RemoteManager rm = RemoteManager.getRemoteManager(server);
/* 553 */     IndexReader indexReader = null;
/*     */     try
/*     */     {
/* 556 */       boolean all = false;
/* 557 */       if ((ids.length == 1) && (ids[0].equals("ALL")))
/*     */       {
/* 559 */         clearIndex();
/* 560 */         all = true;
/*     */       } else {
/* 562 */         indexReader = IndexReader.open(LuceneDirectory.open(this.mIndexPath), false);
/*     */       }
/*     */       
/* 565 */       int done = 0;
/* 566 */       int total = ids.length;
/* 567 */       while (done < total) {
/* 568 */         int last = Math.min(total, done + 50);
/* 569 */         StringBuilder sb = new StringBuilder(128 + last * 12);
/* 570 */         sb.append("zmqaction " + action.toString() + " " + this.mQueueName + " ");
/*     */         
/* 572 */         boolean first = true;
/* 573 */         for (int i = done; i < last; i++) {
/* 574 */           if (first) {
/* 575 */             first = false;
/*     */           } else {
/* 577 */             sb.append(",");
/*     */           }
/* 579 */           if (!all) {
/* 580 */             Term toDelete = new Term(QueueAttr.id.toString(), ids[i].toLowerCase());
/* 581 */             int numDeleted = indexReader.deleteDocuments(toDelete);
/* 582 */             this.mNumMessages.getAndAdd(-numDeleted);
/* 583 */             if (ZimbraLog.rmgmt.isDebugEnabled()) ZimbraLog.rmgmt.debug("deleting term:" + toDelete + ", docs deleted=" + numDeleted);
/*     */           }
/* 585 */           sb.append(ids[i].toUpperCase());
/*     */         }
/* 587 */         done = last;
/* 588 */         rm.execute(sb.toString());
/*     */       }
/*     */       return;
/* 591 */     } catch (IOException ioe) { throw ServiceException.FAILURE("exception occurred performing queue action", ioe);
/*     */     } finally {
/* 593 */       if (indexReader != null)
/*     */         try {
/* 595 */           indexReader.close();
/*     */         } catch (IOException ioe) {
/* 597 */           ZimbraLog.rmgmt.warn("exception occured closing index reader during action", ioe);
/*     */         }
/*     */     }
/*     */   }
/*     */   
/*     */   private static enum TestTask {
/* 603 */     scan,  search,  action;
/*     */     
/*     */     private TestTask() {} }
/* 606 */   private static void usage(String err) { if (err != null) {
/* 607 */       System.err.println("ERROR: " + err + "\n");
/*     */     }
/* 609 */     System.err.println("Usage: " + RemoteMailQueue.class.getName() + " scan|search|action host queue [query] [action-name queueids]");
/* 610 */     System.exit(1);
/*     */   }
/*     */   
/*     */   public static void main(String[] args) throws ServiceException {
/* 614 */     CliUtil.toolSetup("DEBUG");
/* 615 */     Provisioning prov = Provisioning.getInstance();
/*     */     
/* 617 */     if (args.length < 3) {
/* 618 */       usage(null);
/*     */     }
/*     */     
/* 621 */     TestTask task = TestTask.valueOf(args[0]);
/*     */     
/* 623 */     String host = args[1];
/* 624 */     String queueName = args[2];
/*     */     
/* 626 */     Query query = null;
/* 627 */     if (task == TestTask.search) {
/* 628 */       Element queryElement = Element.parseXML(System.in);
/* 629 */       query = GetMailQueue.buildLuceneQuery(queryElement);
/*     */     }
/*     */     
/* 632 */     QueueAction action = null;
/* 633 */     String queueIds = null;
/* 634 */     if (task == TestTask.action) {
/* 635 */       if (args.length < 5) {
/* 636 */         usage("not enough arguments for action");
/*     */       }
/* 638 */       action = QueueAction.valueOf(args[3]);
/* 639 */       if (action == null) {
/* 640 */         usage("invalid action " + args[3]);
/*     */       }
/* 642 */       queueIds = args[4];
/*     */     }
/*     */     
/* 645 */     Server server = prov.get(Key.ServerBy.name, host);
/* 646 */     RemoteMailQueue queue = new RemoteMailQueue(server, queueName, task == TestTask.scan);
/* 647 */     queue.waitForScan(0L);
/*     */     int i;
/* 649 */     Iterator i$; if (task == TestTask.search) {
/* 650 */       SearchResult sr = queue.search(query, 0, 250);
/*     */       
/* 652 */       for (QueueAttr attr : sr.sitems.keySet()) {
/* 653 */         List<SummaryItem> slist = (List)sr.sitems.get(attr);
/* 654 */         System.out.println("qs attr=" + attr);
/* 655 */         Collections.sort(slist);
/* 656 */         for (SummaryItem sitem : slist) {
/* 657 */           System.out.println("   " + sitem.term() + "=" + sitem.count());
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 662 */       i = 0;
/* 663 */       for (i$ = sr.qitems.iterator(); i$.hasNext();) { qitem = (Map)i$.next();
/* 664 */         System.out.println("qi[" + i++ + "]");
/* 665 */         for (QueueAttr attr : qitem.keySet()) {
/* 666 */           System.out.println("   " + attr + "=" + (String)qitem.get(attr));
/*     */         }
/*     */       }
/*     */     }
/*     */     Map<QueueAttr, String> qitem;
/* 671 */     if (task == TestTask.action) {
/* 672 */       queue.action(server, action, queueIds.split(","));
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/rmgmt/RemoteMailQueue.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */